package com.hulk.dryad.manage.framework.websocket.server.handshake;

import com.hulk.dryad.manage.boot.launch.DryadLogLevel;
import com.hulk.dryad.manage.framework.websocket.server.config.WebSocketServerProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;


import org.springframework.util.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 连接时验证用户是否登录
 *
 * @author
 */
@Slf4j
@RequiredArgsConstructor
public class WebSocketAuthHandshakeInterceptor implements HandshakeInterceptor {
	public static final String WS_PRINCIPAL_ATTR_NAME = "__wsPrincipal__";
	private final WebSocketPrincipalResolve principalResolve;
	private final WebSocketServerProperties webSocketProperties;

	@Override
	public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
								   WebSocketHandler wsHandler, Map<String, Object> attributes)  {
		WebSocketServerProperties.Handshake handshake = webSocketProperties.getHandshake();
		// 打印握手的请求信息
		logHandshake(request, handshake.getLogLevel());
		// 解析握手的用户信息
		Principal principal = principalResolve.resolve(request);
		if (principal == null) {
			log.error("WebSocket 握手失败 token is null.");
			return false;
		}
		attributes.put(WS_PRINCIPAL_ATTR_NAME, principal);
		log.info("WebSocket 握手成功 Principal:{}", principal);
		return true;
	}

	@Override
	public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
							   WebSocketHandler wsHandler, Exception exception) {

	}

	/**
	 * 打印 websocket 握手日志打印
	 *
	 * @param request ServerHttpRequest
	 * @param level   LogLevel
	 */
	private static void logHandshake(ServerHttpRequest request, DryadLogLevel level) {
		// 不打印日志，直接返回
		if (DryadLogLevel.NONE == level) {
			return;
		}
		HttpHeaders headers = request.getHeaders();
		StringBuffer logBuffer = new StringBuffer();
		List<Object> logArgs = new ArrayList<>();
		logBuffer.append("\n================  WebSocket Handshake Start  ================\n");
		// 打印路由
		logBuffer.append("===> {}: {}\n");
		logArgs.add(request.getMethodValue());
		logArgs.add(request.getURI());
		// 打印请求头
		if (DryadLogLevel.HEADERS.lte(level)) {
			headers.forEach((name, values) -> {
				logBuffer.append("===Headers===  {}: {}\n");
				logArgs.add(name);
				logArgs.add(StringUtils.collectionToCommaDelimitedString(values));
			});
		}
		logBuffer.append("================  WebSocket Handshake End  ================\n");
		log.info(logBuffer.toString(), logArgs.toArray());
	}

}
